
//一些数组的常用方法实现

const players = [
    { name: '科比', num: 24 },
    { name: '詹姆斯', num: 23 },
    { name: '保罗', num: 3 },
    { name: '威少', num: 0 },
    { name: '杜兰特', num: 35 }
]

//forEach实现
// 参数代表含义
// item：遍历项
// index：遍历项的索引
// arr：数组本身

Array.prototype.sx_forEach = function(callback){
    for(let i = 0; i < this.length; i++){
        callback(this[i], i, this)
    }
}

players.sx_forEach((item,index,array)=>{
    // console.log(item,index,array)
})

//map实现
// 参数代表含义
// item：遍历项
// index：遍历项的索引
// arr：数组本身

Array.prototype.sx_map = function(callback){
    const newArr = []
    for(let i = 0; i < this.length; i++){
        newArr.push(callback(this[i], i, this))
    }
    return newArr
}

// console.log(players.sx_map((item,index) => `${item.name} -- ${item.num} -- ${index}`))

//filter实现
//参数代表含义
// item：遍历项
// index：遍历项的索引
// arr：数组本身

Array.prototype.sx_filter = function(callback){
    const newArr = []
    for(let i = 0; i < this.length; i++){
        callback(this[i],i,this) && newArr.push(this[i])
    }
    return newArr
}

// console.log(players.sx_filter((item,index) => item.num >= 23))

//every实现
Array.prototype.sx_every = function(callback){
    let flag = true
    for(let i = 0; i < this.length; i++){
        flag = callback(this[i], i, this)
        if(!flag) break
    }
    return flag
}
// console.log(players.sx_every(item => item.num > 22))

//some实现
Array.prototype.sx_some = function(callback){
    let flag = false
    for(let i = 0; i < this.length; i++){
        flag = callback(this[i], i, this)
        if(flag) break
    }
    return flag
}
// console.log(players.sx_some(item => item.num > 22))


//reduce 实现
//参数含义
//pre:前一项
//next：下一项
//index：当前索引
//arr：数组本身
const num = [11,23,33,21]
Array.prototype.sx_reduce = function(callback, ...args){
    let start = 0, pre
    if(args.length){
        pre = args[0]
    } else {
        pre = this[0]
        start = 1
    }
    for(let i = start; i < this.length; i++){
        pre = callback(pre,this[i], i, this)
    }
    return pre
}

// const sum = num.sx_reduce((pre,next)=>{ return pre * next },5)
// console.log(sum)

//findIndex实现
Array.prototype.sx_findIndex = function(callback){
    for(let i = 0; i < this.length; i++){
        if(callback(this[i],i,this)){
            return i
        }
    }
    return  -1
}

// console.log(num.sx_findIndex(item=> item == 11))

//find实现
Array.prototype.sx_find = function(callback){
    for(let i = 0; i < this.length; i++){
        if(callback(this[i], i, this)){
            return this[i]
        }
    }
    return undefined
}
// console.log(players.find(item=> item.num == 23))

//fill
//用处：填充数组
//参数代表含义
//initValue: 填充的值
//start: 开始填充索引，默认0
//end: 结束填充索引，默认length
Array.prototype.sx_fill = function(value,start = 0, end){
    end = end || this.length
    for(let i = start; i < end; i++){
        this[i] = value
    }
    return this
}

// console.log(players.sx_fill('299888',3,5))

//includes实现
//用处： 查找元素，查到返回true，反之返回false，可查找NaN
Array.prototype.sx_includes = function(value,start = 0){
    if(start < 0) start = start + this.length
    const isNaN = Number.isNaN(value)
    for(let i = start; i < this.length; i++){
        if(this[i] === value || (isNaN && Number.isNaN(this[i]))){ //NaN数值类型 NaN == NaN 为false
            return true
        }
    }
    return false
}


//join实现 用处：将数组用分隔符拼成字符串，分隔符默认为，
Array.prototype.sx_join = function(s = ','){
    let str = ''
    for(let i = 0; i < this.length; i++){
        str = i === 0 ? `${str}${this[i]}` : `${str}${s}${this[i]}`
    }
    return str
}

//flat实现
Array.prototype.sx_flat = function(){
    let arr = this
    while(arr.some(item=> Array.isArray(item))){
        arr = [].concat(...arr)
    }
    return arr
}

console.log([2,[2,3,[3,6,[5,6]]]].sx_flat())

//1、Array.prototype.splice
//难点： 截取长度和替换长度的比较，不同情况
// 总结： 开始位置截取（位数），返回截取的数组，并改变原数组
Array.prototype.sx_splice = function(start, length, ...values){
    if(length === 0) return []
    length = start + length > this.length - 1 ?  this.length - start : length
    const res = [], tempArr = [...this]

    for(let i = start; i < start + values.length; i++){
        this[i] = values[i - start]
    }
    this.length = start + values.length
    if(values.length < length){
        const cha = length - values.length
        for(let i = start + values.length; i < tempArr.length; i++){
            this[i] = tempArr[i + cha]
        }
        this.length = this.length - cha
    }
    if(values.length > length){
        for(let i = start + length; i < tempArr.length; i++){
           this.push(tempArr[i]) 
        }
    }
    for(let i = start; i < start + length; i++){
        res.push(tempArr[i])
    }
    return res
}

/** 截取从开始位置到结束位置，不包括结束位置，不改变原数组，返回截取的数组，
 * 没有第二个参数则一直截取到最后一位（不包括最后一位，若为-1，则包括最后一位），
 * 若两参数都为负数则不包括开始位置
 * */ 
Array.prototype.sx_slice = function(start, end){}

//shift: 删除原数组第一项，并返回删除元素的值；如果数组为空则返回undefined
Array.prototype.sx_shift = function(){

}

//unshift: 向数组的开头添加一个或更多元素(直接修改原数组)，并返回新的长度
Array.prototype.sx_unshift = function(){}

//在数组尾部逐个添加元素，返回结果数组的长度，能接收任意数量参数，push()修改了原数组。
Array.prototype.sx_push = function(){}

//移除数组最后一项，返回的是被移除项。修改原数组
Array.prototype.sx_pop = function(){}


// 将类数组转化为数组的方法
// Array.from()
// [].slice.apply()
// [...A]
// [].map.call(A,o=>0)
